﻿/*---------------------------------------------------------------- 
Module Name:  Default.aspx.cs
Project:      PandellRandomGenerator
Author:       Mark Hunter
Description:  Generates a list of 10,000 numbers in random order
              each time the 'Generate...' button is selected. 
              Each number in the list must be unique and be
              between 1 and 10,000 (inclusive).
----------------------------------------------------------------*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Threading;
using System.Diagnostics;

namespace PandellRandomGenerator
{
    public partial class Default : System.Web.UI.Page
    {
        /*Page_Load event*/
        protected void Page_Load(object sender, EventArgs e)
        {
            HeaderLabel.Text = "Shuffled List From 1 - 10,000:";
        }

        /*InitiateShuffleBtn_Click event*/
        protected void InitiateShuffleBtn_Click(object sender, EventArgs e)
        {
            Stopwatch stopWatch = new Stopwatch();
            stopWatch.Start();
            var randomList = HelperFunctions.GenerateRandom10000List();
            stopWatch.Stop();
            TimeSpan ts = stopWatch.Elapsed;
            TimeElapsed.Text = "Runtime: (" + ts.TotalMilliseconds.ToString() + "ms)";
            Numbers.DataSource = randomList;
            Numbers.DataBind();
        }

        /*ListBox number selected - No Op*/
        protected void Numbers_SelectedIndexChanged1(object sender, EventArgs e){}
    }

    public static class HelperFunctions
    {
        /*GenerateRandom100000List - creates shuffled list of integer 1-10000 (inclusive)*/
        public static List<int> GenerateRandom10000List()
        {
            var generate = new List<int>(Enumerable.Range(1, 10000));
            generate.Shuffle();
            return generate;
        }
    }

    static class Extensions
    {
        //------------------------------------------------------------
        // Function:    Shuffle
        // Description: Uses Fisher–Yates shuffle algorithm to 
        //              uniquely shuffle a list. 
        // Args:        List (template) 
        //------------------------------------------------------------
        public static void Shuffle<T>(this IList<T> list)
        {
            int i = list.Count;
            while (i > 1)
            {
                --i;
                
                // System.Random is not thread safe so using thread safe version to guarantee randomness.
                int k = ThreadSafeRandom.ThisThreadsRandom.Next(i + 1);
                
                T value = list[k];
                list[k] = list[i];
                list[i] = value;
            }
        }
    }

    public static class ThreadSafeRandom
    {
        [ThreadStatic]
        private static Random _safeRandom; //local static Random object
        
        //------------------------------------------------------------
        // Function:    ThisThreadsRandom
        // Description: Random Number Generator that is thread safe.
        //              Implementation relies on milliseconds elapsed
        //              since system start and the current thread id.
        // Args:        None
        //------------------------------------------------------------
        public static Random ThisThreadsRandom
        {
            get { return _safeRandom ?? (_safeRandom = new Random(unchecked(Environment.TickCount * 31 + Thread.CurrentThread.ManagedThreadId))); }
        }
    }
}